package mp3;

import java.io.File;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.audio.exceptions.CannotWriteException;
import org.jaudiotagger.tag.FieldDataInvalidException;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.KeyNotFoundException;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.id3.ID3v23Frame;

import util.StringUtil;

public class ModifyMP3 {
	
	private final String COPYRIGHT_KEY = "TCOP";
	private String copyrightVal = "";
	
	private AudioFile f;
	private Tag tag;
	private List<FieldKey> fields;
	private Map<FieldKey, String> originalValues;
	private Map<FieldKey, String> finalValues;
	private boolean isClean;
	private File testFile;
	private boolean fromDB;
	
	public ModifyMP3(File testFile, boolean fromDB) {
		this.testFile = testFile;
		this.fromDB = fromDB;
		
		
	}
	
	public void start() throws Exception {
		f = AudioFileIO.read(testFile);
		tag = f.getTag();
		fields = listOfFieldKeysToManage();
		originalValues = readValues();
		//don't modify if encode is MP3
		isClean = isEncoderMP3();
		if(fromDB) {
			finalValues = updateValuesBasedOnDB();
			setFields();
		} else {
			finalValues = modifyValues();
			writeToDatabase();
		}
	}
	
	private Map<FieldKey, String> updateValuesBasedOnDB() throws ClassNotFoundException, SQLException {
		Map<FieldKey, String> values = new HashMap<FieldKey, String>(originalValues);
		String title = originalValues.get(FieldKey.TITLE);
		String album =originalValues.get(FieldKey.ALBUM);
		int year = Integer.valueOf(originalValues.get(FieldKey.YEAR));
		ManageDatabase md = new ManageDatabase();
		MP3Info mp3Info = md.getMP3FromPrimaryKey(title, album, year);
		
		if(!originalValues.get(FieldKey.ARTIST).equals(mp3Info.getArtist())) {
			values.put(FieldKey.ARTIST, mp3Info.getArtist());
		}
		if(!originalValues.get(FieldKey.TRACK).equals(String.valueOf(mp3Info.getTrack()))) {
			values.put(FieldKey.TRACK, String.valueOf(mp3Info.getTrack()));
		}
		if(!originalValues.get(FieldKey.ALBUM_ARTIST).equals(mp3Info.getAlbumArtist())) {
			values.put(FieldKey.ALBUM_ARTIST, mp3Info.getAlbumArtist());
		}
		if(!originalValues.get(FieldKey.COMPOSER).equals(mp3Info.getComposer())) {
			values.put(FieldKey.COMPOSER, mp3Info.getComposer());
		}
		if(!originalValues.get(FieldKey.GENRE).equals(mp3Info.getGenre())) {
			values.put(FieldKey.GENRE, mp3Info.getGenre());
		}
		if(!originalValues.get(FieldKey.RECORD_LABEL).equals(mp3Info.getRecordLabel())) {
			values.put(FieldKey.RECORD_LABEL, mp3Info.getRecordLabel());
		}
		if(!originalValues.get(FieldKey.TRACK_TOTAL).equals(String.valueOf(mp3Info.getTrackTotal()))) {
			values.put(FieldKey.TRACK_TOTAL, String.valueOf(mp3Info.getTrackTotal()));
		}
		if(!originalValues.get(FieldKey.LYRICIST).equals(mp3Info.getLyricist())) {
			values.put(FieldKey.LYRICIST, mp3Info.getLyricist());
		}
		if(!originalValues.get(FieldKey.LYRICS).equals(mp3Info.getLyrics())) {
			values.put(FieldKey.LYRICS, mp3Info.getLyrics());
		}
		if(!originalValues.get(FieldKey.RATING).equals(String.valueOf(mp3Info.getRating()))) {
			values.put(FieldKey.RATING, String.valueOf(mp3Info.getRating()));
		}
		
		return values;
	}

	public boolean isClean() {
		return isClean;
	}
	
	private boolean isEncoderMP3() {
		return originalValues.get(FieldKey.ENCODER).equals("MP3");
	}

	public void setFields() throws KeyNotFoundException, FieldDataInvalidException, CannotWriteException {
		for(Entry<FieldKey, String> e : finalValues.entrySet()) {
			tag.setField(e.getKey(), e.getValue());
			System.out.println(e.getKey()+": "+ e.getValue());
		}
		f.commit();
	}
	
	public void writeToDatabase() throws ClassNotFoundException, SQLException {
		//TODO write/update to db
		MP3Info mp3 = new MP3Info();
		mp3.setTitle(finalValues.get(FieldKey.TITLE));
		mp3.setArtist(finalValues.get(FieldKey.ARTIST));
		mp3.setAlbum(finalValues.get(FieldKey.ALBUM));
		String trackStr = finalValues.get(FieldKey.TRACK);
		if(!trackStr.equals("")) {
			Integer track = Integer.valueOf(trackStr);
			if(track!=null) {
				mp3.setTrack(track);
			}
		}
		
		String yearStr = finalValues.get(FieldKey.YEAR);
		if(!yearStr.equals("")) {
			Integer year = Integer.valueOf(yearStr);
			if(year!=null) {
				mp3.setYear(year);
			}
		}
				
		mp3.setAlbumArtist(finalValues.get(FieldKey.ALBUM_ARTIST));
		mp3.setComposer(finalValues.get(FieldKey.COMPOSER));
		mp3.setGenre(finalValues.get(FieldKey.GENRE));
		mp3.setRecordLabel(finalValues.get(FieldKey.RECORD_LABEL));
		
		String trackTotalStr = finalValues.get(FieldKey.TRACK_TOTAL);
		if(!trackTotalStr.equals("")) {
			Integer trackTotal = Integer.valueOf(trackTotalStr);
			if(trackTotal!=null) {
				 mp3.setTrackTotal(trackTotal);
			}
		} 
		mp3.setLyricist(finalValues.get(FieldKey.LYRICIST));
		mp3.setLyrics(finalValues.get(FieldKey.LYRICS));
		String ratingStr = finalValues.get(FieldKey.RATING);
		if(!ratingStr.equals("")) {
			Integer rating = Integer.valueOf(ratingStr);
			if(rating!=null) {
				mp3.setRating(rating);
			}
		}
		
		ManageDatabase md = new ManageDatabase();
		md.saveMP3(mp3);
	}
	
	private Map<FieldKey, String> readValues() {
		Map<FieldKey, String> values = new HashMap<FieldKey, String>();
		
		for(FieldKey key : fields) {
			ID3v23Frame y = (ID3v23Frame) tag.getFirstField(key);
			if(y==null) {
				System.out.println(key.name()+": BLANK");
				values.put(key, "");
			} else {
				System.out.println(key.name()+": "+ y.getContent());
				values.put(key, y.getContent());
			}
		}
		
		ID3v23Frame y = (ID3v23Frame) tag.getFirstField(COPYRIGHT_KEY);
		System.out.println("Copyright: "+ y.getContent());
		copyrightVal = y.getContent();
		
		return values;
	}
	
	private Map<FieldKey, String> modifyValues() throws Exception {
		Map<FieldKey, String> values = new HashMap<FieldKey, String>(originalValues);

		for(Entry<FieldKey, String> field : originalValues.entrySet()) {
			
			FieldKey fieldKey = field.getKey();
			
			if(fieldKey.equals(FieldKey.TITLE)) {
				values.put(fieldKey, originalValues.get(fieldKey));
			} else if(fieldKey.equals(FieldKey.ARTIST)) {
				values.put(fieldKey, originalValues.get(fieldKey));
			} else if(fieldKey.equals(FieldKey.ALBUM)) {
				String albumName = StringUtil.removeParanData(field.getValue());
				values.put(fieldKey, albumName);
				
			} else if(fieldKey.equals(FieldKey.TRACK)) {
				String val = originalValues.get(fieldKey);
				if(val!=null && !val.isEmpty()) {
					values.put(fieldKey, val);
				} else {
					values.put(fieldKey, "0");
				}
			} else if(fieldKey.equals(FieldKey.YEAR)) {
				String val = originalValues.get(fieldKey);
				if(val!=null && !val.isEmpty()) {
					values.put(fieldKey, val);
				} else {
					values.put(fieldKey, "0");
				}
			} 
			//else if((field.getKey()).equals(FieldKey.ALBUM_ARTIST)) {
				
			//} 
			else if(fieldKey.equals(FieldKey.COMMENT)) {
				values.put(fieldKey, "");
				
			} else if(fieldKey.equals(FieldKey.COMPOSER)) {
				//set album artist too
				Map<String, String> map = getAlbumArtistAndComposer(field.getValue());
				values.put(FieldKey.ALBUM_ARTIST, map.get(FieldKey.ALBUM_ARTIST.name()));
				values.put(FieldKey.COMPOSER, map.get(FieldKey.COMPOSER.name()));
				
			} else if(fieldKey.equals(FieldKey.ENCODER)) {
				values.put(fieldKey, "MP3");
				
			} else if(fieldKey.equals(FieldKey.GENRE)) {
				values.put(fieldKey, "Telugu");
				
			} else if(fieldKey.equals(FieldKey.RECORD_LABEL)) {
				values.put(fieldKey, "");
				
			} else if(fieldKey.equals(FieldKey.TRACK_TOTAL)) {
				String val = originalValues.get(fieldKey);
				if(val!=null && !val.isEmpty()) {
					values.put(fieldKey, val);
				} else {
					values.put(fieldKey, "0");
				}
			} else if(fieldKey.equals(FieldKey.LYRICIST)) {
				values.put(fieldKey, "");
				
			} else if(fieldKey.equals(FieldKey.LYRICS)) {
				values.put(fieldKey, "");
				
			} else if(fieldKey.equals(FieldKey.RATING)) {
				String val = originalValues.get(fieldKey);
				if(val!=null && !val.isEmpty()) {
					values.put(fieldKey, val);
				} else {
					values.put(fieldKey, "0");
				}
				
			} 
		}
		
		//Copyright
		// TODO not worrying about copyright now
//		if(true) {
//			
//		}
		return values;
	}
	
	private Map<String, String> getAlbumArtistAndComposer(String composerStr) throws Exception {
		Map<String, String> map = new HashMap<String, String>(2);
		//Music : Sekhar Chandra | Lyrics : Bhaskarabhatla
		String[] splitter = composerStr.split("\\|");
		String albumArtist = "";
		String composer = "";
		for(String s : splitter) {
			if(s.contains("Music")) {
				albumArtist = s.split(":")[1];
			} else if (s.contains("Lyrics")) {
				composer = s.split(":")[1];
			}
		}
		albumArtist = StringUtil.removeLeadingAndHangingSpaces(albumArtist);
		composer = StringUtil.removeLeadingAndHangingSpaces(composer);
		
		map.put(FieldKey.ALBUM_ARTIST.name(), albumArtist);
		map.put(FieldKey.COMPOSER.name(), composer);
		
		return map;
	}
	
	private List<FieldKey> listOfFieldKeysToManage() {
		List<FieldKey> fieldKeys = new ArrayList<FieldKey>();
		fieldKeys.add(FieldKey.TITLE);
		fieldKeys.add(FieldKey.ARTIST);
		fieldKeys.add(FieldKey.ALBUM);
		fieldKeys.add(FieldKey.TRACK);
		fieldKeys.add(FieldKey.YEAR);
		fieldKeys.add(FieldKey.ALBUM_ARTIST);
		fieldKeys.add(FieldKey.COMMENT);
		fieldKeys.add(FieldKey.COMPOSER);
//		fieldKeys.add(FieldKey.valueOf(COPYRIGHT_KEY));
		fieldKeys.add(FieldKey.ENCODER);
		fieldKeys.add(FieldKey.GENRE);
		fieldKeys.add(FieldKey.RECORD_LABEL);
		fieldKeys.add(FieldKey.TRACK_TOTAL);
		fieldKeys.add(FieldKey.LYRICIST);
		fieldKeys.add(FieldKey.LYRICS);
		fieldKeys.add(FieldKey.RATING);
		return fieldKeys;
	}

}
